package org.tamal.persistence;

import java.util.Set;

import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToMany;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;

/**
 * The Customer class.
 * @author Tamal Kanti Nath
 */
@Entity
@Cacheable
@DynamicUpdate
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Customer extends Person {

    private String pan;
    private String username;
    private String password;
    private Set<Account> accounts;

    /**
     * Returns the pan.
     * @return the pan
     */
    @Column(nullable = false, unique = true, length = 10)
    public String getPan() {
        return pan;
    }

    /**
     * Sets the pan.
     * @param pan the pan to set
     */
    public void setPan(String pan) {
        this.pan = pan;
    }

    /**
     * Returns the accounts.
     * @return the accounts
     */
    @ManyToMany(mappedBy = "customers", cascade = CascadeType.ALL)
    public Set<Account> getAccounts() {
        return accounts;
    }

    /**
     * Sets the accounts.
     * @param accounts the accounts to set
     */
    public void setAccounts(Set<Account> accounts) {
        this.accounts = accounts;
    }

    /**
     * Returns the user name.
     * @return the user name
     */
    @Column(nullable = false, unique = true)
    public String getUsername() {
        return username;
    }

    /**
     * Sets the user name.
     * @param username the user name to set
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * Returns the password.
     * @return the password
     */
    @Column(nullable = false)
    public String getPassword() {
        return password;
    }

    /**
     * Sets the password.
     * @param password the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * Indicates whether the specified object equals to this object.<br/>
     * For Customer entity, the PAN is the business key. Two customers are
     * considered equal if their PAN are equal.
     *
     * @param obj the reference object with which to compare
     * @return if this Customer is the same as the obj argument; false otherwise
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Employee)) {
            return false;
        }
        return pan.equals(((Customer) obj).pan);
    }

    /**
     * The hash code is generated from pan (Permanent Account Number).
     * @return hash code value for customer
     */
    @Override
    public int hashCode() {
        return pan.hashCode();
    }

    @Override
    public String toString() {
        return super.toString() + " PAN: " + pan + " username: " + username;
    }
}
